home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample SMSAM / SampleSMSAM Source / BuildingBlocks / TranscriptWindow.cp < prev    next >
Encoding:
Text File  |  1995-07-28  |  24.5 KB  |  1,092 lines  |  [TEXT/R*ch]

  1. /*
  2.     File:        TranscriptWindow.cp
  3.  
  4.     Copyright:    © 1991-1994 by Apple Computer, Inc.
  5.                 All rights reserved.
  6.  
  7.     Part of the AOCE Sample SMSAM Package.  Consult the license
  8.     which came with this software for your specific legal rights.
  9.  
  10. */
  11.  
  12.  
  13.  
  14. #ifndef __TRANSCRIPTWINDOW__
  15. #include "TranscriptWindow.h"
  16. #endif
  17.  
  18. #ifndef __TYPES__
  19. #include <Types.h>
  20. #endif
  21.  
  22. #ifndef __FONTS__
  23. #include "FONTS.h"
  24. #endif
  25.  
  26. #ifndef __MENUS__
  27. #include <Menus.h>
  28. #endif
  29.  
  30. #ifndef __WINDOWS__
  31. #include <Windows.h>
  32. #endif
  33.  
  34. #ifndef __WRITELINEWINDOW__
  35. #include "WriteLineWindow.h"
  36. #endif
  37.  
  38. #ifndef __MEMORY__
  39. #include <Memory.h>
  40. #endif
  41.  
  42. #ifndef __LIMITS__
  43. #include <Limits.h>
  44. #endif
  45.  
  46. #ifndef __ERRORS__
  47. #include <Errors.h>
  48. #endif
  49.  
  50. #ifndef __EVENTS__
  51. #include <Events.h>
  52. #endif
  53.  
  54. #ifndef __OSEVENTS__
  55. #include <OSEvents.h>
  56. #endif
  57.  
  58. #ifndef __STDIO__
  59. #include <stdio.h>
  60. #endif
  61.  
  62. #ifndef __OBJECTLIST__
  63. #include "ObjectList.h"
  64. #endif
  65.  
  66. /***********************************|****************************************/
  67.  
  68. #pragma segment TranscriptWindow
  69.  
  70. /***********************************|****************************************/
  71.  
  72. DeclareList ( TTranscriptWindow, TTranscriptWindowList );
  73. ImplementList ( TTranscriptWindow, TTranscriptWindowList , true );
  74.  
  75. /***********************************|****************************************/
  76.  
  77. TTranscriptWindowList                        gTranscriptWindowList;
  78.  
  79. /***********************************|****************************************/
  80.  
  81. static VHSelect    gOrthogonal[2] = { h, v };
  82.  
  83. /***********************************|****************************************/
  84.  
  85. static RgnHandle GetSaveVisRgn(void)
  86. {
  87.     const long addr    = 0x09F2;
  88.     
  89.     return * (RgnHandle *) addr;
  90. }
  91.  
  92. /***********************************|****************************************/
  93.  
  94. inline VHSelect LongerSide(Rect& r)
  95. {
  96.     if ((r.bottom - r.top) >= (r.left - r.right))
  97.         return v;
  98.     else
  99.         return h;
  100. }
  101.  
  102. /***********************************|****************************************/
  103.  
  104. typedef struct LogInfoRecord
  105. {
  106.     Str31            fontName;
  107.     short            fontSize;
  108.     short            lines;
  109.     short            columns;
  110. } LogInfoRecord, *LogInfoRecordPtr, **LogInfoRecordHandle;
  111.  
  112. /***********************************|****************************************/
  113.  
  114. static short GetFontNumber ( StringPtr fontName )
  115. {
  116.     short result;
  117.     
  118.     GetFNum ( fontName, & result );
  119.     
  120.     return result;
  121. }
  122.  
  123. /***********************************|****************************************/
  124.  
  125. TTranscriptWindow::TTranscriptWindow ( short windowID ) :
  126.     fWindowResID ( windowID ),
  127.     fDebugWindowPtr ( nil ),
  128.     fText ( nil ),
  129.     fLineLens ( nil ),
  130.     fFirst ( 0 ),
  131.     fLast ( 0 ),
  132.     fPos ( 0 ),
  133.     fHeigth ( 0 ),
  134.     fARgn ( nil ),
  135.     
  136.     fGotRefNum ( false ),
  137.     fRefNum ( 0 ),
  138.     fVRefNum ( 0 ),
  139.     
  140.     fScrollWindowWhenTextIsAdded ( true ),
  141.     fWrToWindow ( true ),
  142.     fWrToFile ( false ),
  143.     
  144.     fDirty ( false )
  145. {
  146.     //    Get the information about the size of buffer for this window.
  147.     LogInfoRecordHandle logInfoH = ( LogInfoRecordHandle ) GetResource ( 'LINF', windowID );
  148.     if ( logInfoH )
  149.     {
  150.         fFaceInfo.tsFont = GetFontNumber ( (**logInfoH).fontName );
  151.         fFaceInfo.tsFace = 0;
  152.         fFaceInfo.tsSize = (**logInfoH).fontSize;
  153.         fFaceInfo.tsColor.red = fFaceInfo.tsColor.green = fFaceInfo.tsColor.blue = 0;
  154.         fLines = (**logInfoH).lines;
  155.         fPerLine = (**logInfoH).columns;
  156.     }
  157.     else
  158.     {
  159.         fFaceInfo.tsFont = GetFontNumber ( "\pMonaco" );
  160.         fFaceInfo.tsFace = 0;
  161.         fFaceInfo.tsSize = 12;
  162.         fFaceInfo.tsColor.red = fFaceInfo.tsColor.green = fFaceInfo.tsColor.blue = 0;
  163.         fLines = 120;
  164.         fPerLine = 80;
  165.     }
  166.     
  167.     fTotal = fLines * fPerLine;
  168.     
  169.     
  170.     fSBars [ v ] = fSBars [ h ] = nil;
  171.  
  172.     SetRect(&fStdDrag, 4, 24, qd.screenBits.bounds.right - 4, qd.screenBits.bounds.bottom - 4);    //this is suggested in Inside Macintosh
  173.     SetRect(&fStdSize, 20, 20, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom - 20);        //arbitrary Minimum size; Maximum size is screen
  174.  
  175.     fViewSize.v = fViewSize.h = 0;
  176.     fEndOfText.v = fEndOfText.h = 0;
  177.     
  178.     fText = (char **) NewHandleClear(fTotal);
  179.     if (fText == NULL)
  180.     {
  181.         DebugStr ("\pNot enough memory to allocate the Debug Window''s Line Array: " );
  182.         return ;
  183.     }
  184.  
  185.     fLineLens = (short **) NewHandleClear ( fLines * sizeof ( (*fLineLens)[0] ) );
  186.     if (fLineLens == NULL)
  187.     {
  188.         DisposeHandle(Handle(fText));
  189.         DebugStr ("\pNot enough memory to allocate the Debug Window''s LineLen Array: ");
  190.         return;
  191.     }
  192.  
  193.     fLast = fTotal - fPerLine;
  194.  
  195.     gTranscriptWindowList.Append ( this );
  196. }
  197.  
  198. /***********************************|****************************************/
  199.  
  200. TTranscriptWindow::~TTranscriptWindow ( )
  201. {
  202.     gTranscriptWindowList.Remove ( this );
  203. }
  204.  
  205. /***********************************|****************************************/
  206.  
  207. void SetResourceNoPurge ( OSType resType, short resID )
  208. {
  209.     Handle h = GetResource ( resType, resID );
  210.     if ( h )
  211.         HNoPurge ( h );
  212. }
  213.  
  214. /***********************************|****************************************/
  215.  
  216. Boolean TTranscriptWindow::Initialize ( )
  217. {
  218.  
  219.     GrafPtr        savePort;
  220.  
  221.     GetPort(&savePort);
  222.     if ( fDebugWindowPtr == nil )
  223.     {    Rect bounds = { 40, 16, 40+12*36, 16+6*80+16 };
  224.         Boolean goAway = true, visible = false;
  225.  
  226.         fDebugWindowPtr = GetNewWindow ( fWindowResID, nil, (WindowPtr) -1 );
  227.         ((WindowPeek) fDebugWindowPtr)->refCon = (long) this;
  228.         // fDebugWindowPtr = Neindow(nil, & bounds, "\p", visible, documentProc, (WindowPtr) -1, goAway, 0);
  229.  
  230.         #if 0
  231.         Boolean RectOnScreen ( const Rect & rect );
  232.         if ( ! RectOnScreen ( fDebugWindowPtr->portRect ) )
  233.         {
  234.             Rect r = 
  235.         
  236.         }
  237.         #endif
  238.  
  239.         SetRect(&fStdDrag, 4, 24, qd.screenBits.bounds.right - 4, qd.screenBits.bounds.bottom - 4);    //this is suggested in Inside Macintosh
  240.         SetRect(&fStdSize, 20, 20, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom - 20);        //arbitrary Minimum size; Maximum size is screen
  241.  
  242.         fARgn = NewRgn();
  243.  
  244.         SetPt(&fEndOfText, kHMargin, (short) BaseLine(fLines));
  245.  
  246.         SetPort(fDebugWindowPtr);
  247.  
  248.         //    Now, get the information about this font's width, etc.
  249.         TextFont ( fFaceInfo.tsFont );
  250.         TextSize ( fFaceInfo.tsSize );
  251.         TextFace ( fFaceInfo.tsFace );
  252.         GetFontInfo ( & fFontInfo );
  253.         fHeigth = fFontInfo.ascent + fFontInfo.descent + fFontInfo.leading;
  254.     
  255.  
  256.         fHeigth = fFontInfo.ascent + fFontInfo.descent + fFontInfo.leading;
  257.         SetPt(&fViewSize, (2 * kHMargin) + (fPerLine * fFontInfo.widMax), (2 * kVMargin) + (fHeigth * fLines));
  258.  
  259.         //    Make the debugging window font non-purgeable
  260.         SetResourceNoPurge ( 'FOND', fFaceInfo.tsFont );
  261.         SetResourceNoPurge ( 'FONT', fFaceInfo.tsFont );
  262.  
  263.         //scroll bars
  264.         for ( VHSelect vhs = v; vhs <= h; ++ vhs ) {
  265.             fSBars[vhs] = NewControl(fDebugWindowPtr, &fDebugWindowPtr->portRect, "\p", false, 0, 0, 1, scrollBarProc, 0);
  266.             (**fSBars[vhs]).contrlRfCon = (long) this;
  267.         }
  268.  
  269.         fScrollOffset.v = fScrollOffset.h = 0;
  270.  
  271.         //put the scroll bars in the right place
  272.         Grown();
  273.  
  274.         //force an update
  275.         UpdateEvent();
  276.  
  277.         //scroll to the end, in case there is some information that needs to be displayed
  278.         SetCtlValue(fSBars[v], LONG_MAX);
  279.         DoScrolling();
  280.  
  281.     }
  282.     SetPort(savePort);
  283.  
  284.     return true;
  285. }
  286.  
  287. /***********************************|****************************************/
  288.  
  289. void TTranscriptWindow::WindowFocus(void)
  290. {
  291.     SetPort(fDebugWindowPtr);
  292.     SetOrigin(0, 0);
  293.     ClipRect(&qd.thePort->portRect);
  294. }
  295.  
  296. /***********************************|****************************************/
  297.  
  298. void TTranscriptWindow::ContentFocus(void)
  299. {    Rect        r;
  300.  
  301.     SetPort(fDebugWindowPtr);
  302.     SetOrigin(fScrollOffset.h, fScrollOffset.v);
  303.     * ( Rect *) &r = * ( Rect *) & qd.thePort->portRect;
  304.     r.right = r.right - 15;
  305.     r.bottom = r.bottom - 15;
  306.     ClipRect(&r);
  307. }
  308.  
  309. /***********************************|****************************************/
  310.  
  311. void TTranscriptWindow::ActivateEvent(short modifiers)
  312. {    Rect r;
  313.         GrafPtr        savePort;
  314.  
  315.     GetPort(&savePort);
  316.  
  317.     WindowFocus();
  318.  
  319.     r = qd.thePort->portRect;
  320.  
  321.     if ( modifiers & 0x01 )
  322.     {
  323.         ShowControl ( fSBars[v] );
  324.         ShowControl ( fSBars[h] );
  325.     }
  326.     else
  327.     {
  328.         HideControl ( fSBars[v] );
  329.         HideControl ( fSBars[h] );
  330.     }
  331.  
  332.     DrawGrowIcon(fDebugWindowPtr);
  333.  
  334.     SetPort(savePort);
  335. }
  336.  
  337. /***********************************|****************************************/
  338.  
  339. void TTranscriptWindow::Append(Ptr textBuf, long byteCount)
  340. {
  341.     GrafPtr        savePort;
  342.     Rect        r;
  343.  
  344.  
  345.     if ( byteCount <= 0 )
  346.         return;
  347.  
  348.     fDirty = fDirty && ( byteCount > 0 );
  349.         
  350.     if (fWrToFile)
  351.         if (fGotRefNum)
  352.         {    long count = byteCount;
  353.             FSWrite(fRefNum, &count, textBuf);
  354.  
  355.             long        filePos ;
  356.             if ( GetFPos (fRefNum, &filePos) == noErr) 
  357.                 if ( SetEOF (fRefNum, filePos) == noErr ) 
  358.                     FlushOutputFile();
  359.         }
  360.  
  361.     if (fWrToWindow)
  362.     {
  363.         if (fDebugWindowPtr != NULL)
  364.             GetPort(&savePort);
  365.  
  366.         Boolean deleted = false;
  367.  
  368.         while ( byteCount > 0)
  369.         {
  370.             Boolean gotEOL = false;
  371.             Ptr startPtr = textBuf;
  372.             long startCount = byteCount;
  373.  
  374.             while ( (byteCount > 0) && (fPos < fPerLine) && ( !gotEOL ) )
  375.             {
  376.                 QDByte b = * textBuf ;
  377.                 byteCount --;
  378.                 textBuf ++ ;
  379.  
  380.                 if ( (b == 13) || ( b == 10 ) )
  381.                 {    b = 13;
  382.                     gotEOL = true;
  383.                     break;
  384.                 }
  385.                 else if (b != 8)
  386.                 {
  387.                     (*fText)[fLast+fPos++] = b;
  388.                 } 
  389.                 else if (fPos > 0)  // Backspace -- don't backspace past beginning of line!
  390.                 {
  391.                     SetRect(&r, fEndOfText.h - fFontInfo.widMax, fEndOfText.v - fFontInfo.ascent, fEndOfText.h, fEndOfText.v + fHeigth - fFontInfo.ascent);
  392.                     fEndOfText.h = fEndOfText.h - fFontInfo.widMax;
  393.  
  394.                     if (fDebugWindowPtr != NULL)
  395.                     {
  396.                         ContentFocus();
  397.                         EraseRect(&r);
  398.                     }
  399.  
  400.                     fPos--;
  401.                     deleted = true;
  402.                 }                
  403.                 else
  404.                     deleted = true;
  405.             }
  406.  
  407.             if (!deleted && (fDebugWindowPtr != NULL))
  408.             {
  409.                 ContentFocus();
  410.                 MoveTo(fEndOfText.h, fEndOfText.v);
  411.                 DrawText(QDPtr(startPtr), 0, (short) (startCount - byteCount - gotEOL) );
  412.  
  413.                 PenState        ps;
  414.                 GetPenState(&ps);
  415.                 fEndOfText = ps.pnLoc;
  416.             }
  417.  
  418.             if ((fPos >= fPerLine) || gotEOL)
  419.             {
  420.                 (*fLineLens)[fLast / fPerLine] = fPos;    //remember # characters in this line
  421.  
  422.                 NewLine();
  423.                 if ((byteCount > 0) && (!gotEOL))
  424.                 {
  425.                     (*fText)[fLast] = '…';
  426.                     fPos = 1;
  427.                 }
  428.             }
  429.         }
  430.  
  431.         (*fLineLens)[fLast / fPerLine] = fPos;
  432.  
  433.         if (fDebugWindowPtr != NULL)
  434.             SetPort(savePort);
  435.     }
  436. }
  437.  
  438. /***********************************|****************************************/
  439.  
  440. void TTranscriptWindow::FlushOutputFile(void)
  441. {
  442.     if ( fWrToFile && fDirty )
  443.     {    ParamBlockRec    pb;
  444.  
  445.         pb.ioParam.ioRefNum = fRefNum;
  446.         
  447.         PBFlushFileSync(&pb);
  448.         fDirty = false;
  449.     }
  450. }
  451.  
  452. /***********************************|****************************************/
  453.  
  454. long TTranscriptWindow::BaseLine(short ln)
  455. {
  456.     return kVMargin + (ln - 1) * fHeigth;
  457. }
  458.  
  459. /***********************************|****************************************/
  460.  
  461. void TTranscriptWindow::DoScrolling(void)
  462. {    Point newOffset;
  463.     Point delta;
  464.         
  465.     newOffset.v = GetCtlValue(fSBars[v]);
  466.     delta.v = fScrollOffset.v - newOffset.v;
  467.     newOffset.h = GetCtlValue(fSBars[h]);
  468.     delta.h = fScrollOffset.h - newOffset.h;
  469.  
  470.     if ((delta.h != 0) || (delta.v != 0))
  471.     {
  472.         ContentFocus();
  473.  
  474.         ScrollRect(&qd.thePort->portRect, delta.h, delta.v, fARgn);
  475.         fScrollOffset = newOffset;
  476.  
  477.         InvalRgn(fARgn);
  478.  
  479.         UpdateEvent();
  480.     }
  481. }
  482.  
  483. /***********************************|****************************************/
  484.  
  485. void TTranscriptWindow::Draw ( ) const
  486. {
  487.     if ( fDebugWindowPtr) 
  488.         Draw ( fDebugWindowPtr->portRect );
  489. }
  490.  
  491. /***********************************|****************************************/
  492.  
  493.  
  494. void TTranscriptWindow::Draw( const Rect& drawRect ) const
  495. {    
  496. //    PenState        ps;
  497.  
  498.     //    Expand the rect so that in includes enough extra space for a
  499.     //    line of text above and below the actual rect.  Expand the
  500.     //    left and right sides of the rect to match the portRect.
  501.     Rect clipRect = drawRect;
  502.     clipRect.top -= fHeigth;
  503.     clipRect.bottom += fHeigth;
  504.     
  505.     short y = kVMargin;            //initial y corodinate
  506.  
  507.     long start = fFirst;            //offset to first character of next line to draw
  508.     long line = start / fPerLine; //index into fLineLens array for next line to draw; always start / fPerLine
  509.  
  510.     for ( long i = 1; i <= fLines; ++i )
  511.     {
  512.         if ( ( y >= clipRect.top ) && ( y <= clipRect.bottom ) )
  513.         {
  514.             MoveTo(kHMargin, y);
  515.  
  516.             HLock(Handle(fText));
  517.             DrawText(QDPtr((*fText)), (short) start, (short) (*fLineLens)[line]);
  518.             HUnlock(Handle(fText));
  519.         }
  520.  
  521.         y += fHeigth;
  522.         start = start + fPerLine;
  523.         line++;
  524.  
  525.         if (start == fTotal)
  526.         {
  527.             start = line = 0;
  528.         }
  529.     }
  530.  
  531. //    GetPenState(&ps);            //remember position of last character drawn
  532. //    fEndOfText = ps.pnLoc;
  533.  
  534. }
  535.  
  536. /***********************************|****************************************/
  537.  
  538. void TTranscriptWindow::Grown(void)
  539. {    Rect        r;
  540.         ControlHandle        anSBar;
  541.         short        newMax;
  542.         GrafPtr        savePort;
  543.  
  544.     GetPort(&savePort);
  545.  
  546.     WindowFocus();
  547.     SetRect (&r, 0, 0, 0, 0 );
  548.     ClipRect(&r);
  549.  
  550.     for (VHSelect vhs = v; vhs <= h; ++vhs )
  551.     {
  552.         anSBar = fSBars[vhs];
  553.  
  554.         r = qd.thePort->portRect;
  555.  
  556.         // Calculate new position of scroll bar
  557.         (( short *) &r.top)[vhs] = (( short *) &r.top)[vhs] - 1;
  558.         (( short *) &r.top)[gOrthogonal[vhs]] = (( short *) &r.bottom)[gOrthogonal[vhs]] - 15;
  559.         (( short *) &r.bottom)[vhs] = (( short *) &r.bottom)[vhs] - 14;
  560.         (( short *) &r.bottom)[gOrthogonal[vhs]] = (( short *) &r.top)[gOrthogonal[vhs]] + 16;
  561.  
  562.         //Move the scroll bar
  563.         MoveControl(anSBar, r.left, r.top);
  564.         SizeControl(anSBar, r.right-r.left, r.bottom-r.top);
  565.  
  566.         if ( vhs == v )
  567.             newMax = fViewSize.v - (r.bottom - r.top);
  568.         else
  569.             newMax = fViewSize.h - (r.right - r.left );
  570.         
  571.         if (newMax < 0)
  572.             newMax = 0;
  573.         SetCtlMax(anSBar, newMax);
  574.     }
  575.  
  576.     InvalGrowBox();
  577.  
  578.     DoScrolling();    //in case we are showing too much white space
  579.  
  580.     SetPort(savePort);
  581. }
  582.  
  583.  
  584. void TTranscriptWindow::InvalGrowBox(void)
  585. {    Rect     r;
  586.  
  587.     r = qd.thePort->portRect;
  588.     r.top = r.bottom - 15;
  589.     r.left = r.right - 15;
  590.  
  591.     InvalRect(&r);
  592. }
  593.  
  594. /***********************************|****************************************/
  595.  
  596. Boolean GetDefaultWindowInformation ( short dialogID, Boolean& visible, Rect & screenRect );
  597. Boolean SetDefaultWindowInformation ( DialogPtr dP, short dialogID );
  598.  
  599. /***********************************|****************************************/
  600.  
  601. void TTranscriptWindow::MouseDown(short where, Point pt, short modifiers)
  602. {    GrafPtr        savePort;
  603.     
  604.     GetPort(&savePort);
  605.  
  606.     switch (where) {
  607.         case inDrag:
  608.             DragWindow(fDebugWindowPtr, pt, &fStdDrag);
  609.             break;
  610.             
  611.         case inGrow:
  612.             WindowFocus();
  613.  
  614.             long frowResult = GrowWindow(fDebugWindowPtr, pt, &fStdSize);
  615.             if (frowResult != 0)
  616.             {    short newH = (short) (frowResult & 0xffff );
  617.                 short newV = (short) (frowResult >> 16);
  618.                 
  619.                 InvalGrowBox();
  620.                 SizeWindow(fDebugWindowPtr, newH, newV, true);
  621.                 SetDefaultWindowInformation ( fDebugWindowPtr, -1 );
  622.  
  623.                 Grown();
  624.             }
  625.             break;
  626.             
  627.         case inGoAway:
  628.             if (TrackGoAway(fDebugWindowPtr, pt)) {
  629.                 SetDefaultWindowInformation ( fDebugWindowPtr, -1 );
  630.                 HideWindow(fDebugWindowPtr);
  631.             }
  632.             break;
  633.             
  634.         case inContent:
  635.             if (fDebugWindowPtr == FrontWindow())
  636.             {
  637.                 WindowFocus();
  638.                 GlobalToLocal(&pt);
  639.                 
  640.                 ControlHandle whichControl;
  641.                 long partCode = FindControl(pt, fDebugWindowPtr, &whichControl);
  642.                 switch (partCode) 
  643.                 {
  644.                     case inUpButton:
  645.                     case inDownButton:
  646.                     case inPageUp:
  647.                     case inPageDown:
  648.                         pascal void TrackControlCallback ( ControlHandle aControl, short partCode );
  649.                         partCode = TrackControl(whichControl, pt, NewControlActionProc(ProcPtr) TrackControlCallback);
  650.                         DoScrolling();
  651.                         WindowFocus();
  652.                         break;
  653.                         
  654.                     case inThumb:
  655.                         partCode = TrackControl(whichControl, pt, NULL);
  656.                         DoScrolling();
  657.                         break;
  658.                     
  659.                     case 0:
  660.                         break;
  661.                 }
  662.             }
  663.             else
  664.                 SelectWindow(fDebugWindowPtr);
  665.                 
  666.             break;            
  667.     }
  668.  
  669.     SetPort(savePort);
  670. }
  671.  
  672. /***********************************|****************************************/
  673.  
  674. void TTranscriptWindow::NewLine(void)
  675. {    GrafPtr         savePort;
  676.         Point        pt;
  677.         Rect        r;
  678.  
  679.     GetPort(&savePort);
  680.  
  681.     SetPt(&pt, kHMargin, fEndOfText.v);
  682.  
  683.     if ( fScrollWindowWhenTextIsAdded )
  684.         ShowPoint(pt);
  685.     
  686.     fLast = fFirst;
  687.     fPos = 0;
  688.     (*fLineLens)[fLast / fPerLine] = fPos;    //remember # characters in new line
  689.  
  690.     fFirst = fFirst + fPerLine;
  691.     if (fFirst == fTotal)
  692.         fFirst = 0;
  693.  
  694.     SetPt(&fEndOfText, kHMargin, (short) BaseLine(fLines) );
  695.  
  696.     if ( fDebugWindowPtr )
  697.     {
  698.         ContentFocus();
  699.         
  700.         SetRect(&r, kHMargin, kVMargin - fFontInfo.ascent, fViewSize.h, fEndOfText.v + fHeigth - fFontInfo.ascent);
  701.         ScrollRect(&r, 0, -fHeigth, fARgn);
  702.  
  703.         InvalRgn(fARgn);
  704.         UpdateEvent();
  705.     }
  706.  
  707.     SetPort(savePort);
  708. }
  709.  
  710. /***********************************|****************************************/
  711.  
  712. OSErr TTranscriptWindow::Redirect(short vRefNum, long dirID, Str255 fileNameBase, Boolean append )
  713. {    OSErr         err;
  714.     long        x;
  715.  
  716.     if (fGotRefNum)
  717.     {
  718.         // Truncate the file to current position
  719.         err = GetFPos(fRefNum, &x);
  720.         err = SetEOF(fRefNum, x);
  721.  
  722.         if (FSClose(fRefNum) != noErr) /*??? error closing file ???*/;
  723.             if (FlushVol(NULL, fVRefNum) != noErr) /*??? Another fine mess ???*/;
  724.                 fGotRefNum = false;
  725.     }
  726.     
  727.     Str255 fileName;
  728.     PLstrcpy ( fileName, fileNameBase );
  729.     
  730.     if ( PLstrlen(fileName) > 0 )
  731.     {
  732.         err = HCreate(vRefNum, dirID, fileName, 'R*ch', 'TEXT');
  733.  
  734.         if ((err == noErr) || (err == dupFNErr))
  735.         {
  736.             err = HOpen(vRefNum, dirID, fileName, fsRdWrPerm, &fRefNum);
  737.             fVRefNum = vRefNum;
  738.  
  739.             fGotRefNum = err == noErr;
  740.  
  741.             if (fGotRefNum)
  742.                 if (append)
  743.                 {
  744.                     err = GetEOF(fRefNum, &x);
  745.                     err = SetFPos(fRefNum, fsFromStart, x);
  746.                 }
  747.                 else
  748.                     err = SetEOF (fRefNum, 0);
  749.             else
  750.                 err = noErr;
  751.         }
  752.     }
  753.     
  754.     fWrToFile = ( err == noErr );
  755.     
  756.     return noErr;
  757. }
  758.  
  759. /***********************************|****************************************/
  760.  
  761. void TTranscriptWindow::Scroll(short howManyLines)
  762. {    short     val;
  763.         GrafPtr        savePort;
  764.  
  765.     GetPort(&savePort);
  766.     val = GetCtlValue(fSBars[v]);
  767.     if (((howManyLines < 0) && (val > GetCtlMin(fSBars[v]))) ||
  768.        ((howManyLines > 0) && (val < GetCtlMax(fSBars[v]))))
  769.     {
  770.         SetCtlValue(fSBars[v], val + howManyLines * fHeigth);
  771.         DoScrolling();
  772.     }
  773.     SetPort(savePort);
  774. }
  775.  
  776. /***********************************|****************************************/
  777.  
  778. void TTranscriptWindow::ShowPoint(Point pt)
  779. {    Point     minToSee;
  780.         short        deltaCd;
  781.  
  782.     if (fDebugWindowPtr != NULL)
  783.     {
  784.         WindowFocus();
  785.  
  786.         SetPt(&minToSee, 50, fHeigth);
  787.  
  788.         // the following code is actually better than writing a loop with VHSelect
  789.         deltaCd = pt.v + minToSee.v - (qd.thePort->portRect.bottom - 15 + fScrollOffset.v);
  790.         if (deltaCd <= 0)
  791.         {
  792.             deltaCd = pt.v - minToSee.v - (qd.thePort->portRect.top + fScrollOffset.v);
  793.             if (deltaCd >= 0)
  794.                 deltaCd = 0;
  795.         }
  796.         SetCtlValue(fSBars[v], GetCtlValue(fSBars[v]) + deltaCd);
  797.  
  798.         deltaCd = pt.h + minToSee.h - (qd.thePort->portRect.right - 15 + fScrollOffset.h);
  799.         if (deltaCd <= 0)
  800.         {
  801.             deltaCd = pt.h - minToSee.h - (qd.thePort->portRect.left + fScrollOffset.h);
  802.             if (deltaCd >= 0)
  803.                 deltaCd = 0;
  804.         }
  805.         SetCtlValue(fSBars[h], GetCtlValue(fSBars[h]) + deltaCd);
  806.  
  807.         DoScrolling();
  808.     }
  809. }
  810.  
  811. /***********************************|****************************************/
  812.  
  813. pascal void TrackControlCallback ( ControlHandle aControl, short partCode )
  814. {
  815.     if (partCode != 0)
  816.     {
  817.         TTranscriptWindow* logWindow = (TTranscriptWindow *) (**aControl).contrlRfCon;
  818.         
  819.         Boolean up = (partCode == inUpButton) || (partCode == inPageUp);
  820.         short ctlValue = GetCtlValue(aControl);
  821.  
  822.         //    Avoid flicker in setting thumb, if (user tries to scroll past end
  823.         if ((up && (ctlValue > GetCtlMin(aControl))) ||
  824.            (!up && (ctlValue < GetCtlMax(aControl))))
  825.         {
  826.             Rect r = (*aControl)->contrlRect;   //    heap may compact when we call LongerSide
  827.             VHSelect vhs = LongerSide(r);        //    this tells us which way we are scrolling
  828.  
  829.             short delta = 10;
  830.             
  831.             if ( logWindow )
  832.             {    WindowPtr ourWindow = logWindow->GetWindowPtr();
  833.             
  834.                 if ((partCode == inPageUp) || (partCode == inPageDown) && ourWindow )
  835.                     if ( vhs == v )
  836.                         delta = ourWindow->portRect.bottom - ourWindow->portRect.top;
  837.                     else
  838.                         delta = ourWindow->portRect.right - ourWindow->portRect.left;
  839.                 else
  840.                     delta = logWindow->fHeigth;
  841.             }
  842.             
  843.             if (up)
  844.                 delta = - delta;
  845.  
  846.             SetCtlValue(aControl, ctlValue + delta);
  847.             
  848.             if ( logWindow )
  849.             {
  850.                 logWindow->DoScrolling();
  851.                 logWindow->WindowFocus();
  852.             }
  853.         }
  854.     }
  855. }
  856.  
  857. /***********************************|****************************************/
  858.  
  859. Rect GetRegionBoundingRect ( RgnHandle rgn )
  860. {    
  861.     if ( rgn )
  862.         return ( ** rgn ).rgnBBox;
  863.     Rect r = { -32767, -32767, 32767, 32767 };
  864.     return r;
  865. }
  866.  
  867. /***********************************|****************************************/
  868.  
  869. void TTranscriptWindow::UpdateEvent(void)
  870. {    GrafPtr         savePort;
  871.     RgnHandle        saveSaveVisRgn;
  872.     RgnHandle        saveVisRgn;
  873.  
  874.     if ((fDebugWindowPtr != NULL) &&
  875.         (!EmptyRgn( ((WindowPeek) fDebugWindowPtr)->port.visRgn))) 
  876.     {
  877.         GetPort(&savePort);
  878.  
  879.         saveSaveVisRgn = NewRgn();
  880.         saveVisRgn = GetSaveVisRgn();
  881.  
  882.         CopyRgn(saveVisRgn, saveSaveVisRgn);
  883.  
  884.         BeginUpdate(fDebugWindowPtr);
  885.  
  886.         WindowFocus();
  887.  
  888.         EraseRect(&qd.thePort->portRect);
  889.  
  890.         DrawGrowIcon(fDebugWindowPtr);
  891.         DrawControls(fDebugWindowPtr);
  892.  
  893.         ContentFocus();
  894.         
  895.         Rect updateRect = GetRegionBoundingRect ( fDebugWindowPtr->visRgn );
  896.         
  897.         Draw( );
  898.  
  899.         EndUpdate(fDebugWindowPtr);
  900.  
  901.         CopyRgn(saveSaveVisRgn, saveVisRgn);
  902.         DisposeRgn(saveSaveVisRgn);
  903.  
  904.         SetPort(savePort);
  905.     }
  906. }
  907.  
  908. /***********************************|****************************************/
  909.  
  910. WindowPtr TTranscriptWindow::GetWindowPtr ( ) const
  911. {
  912.     return fDebugWindowPtr;
  913. }
  914.  
  915. /***********************************|****************************************/
  916.  
  917. static TTranscriptWindow* FindLogWindow ( WindowPtr wP )
  918. {
  919.     for ( unsigned long index = 1; index <= gTranscriptWindowList.Count (); ++ index )
  920.         if ( gTranscriptWindowList.Get ( index )->GetWindowPtr() == wP )
  921.             return gTranscriptWindowList.Get ( index );
  922.         
  923.     return nil;
  924. }
  925.  
  926. /***********************************|****************************************/
  927.  
  928. /*
  929. --    Paul's Writeln routines  ----------------------------------------------------------------
  930. */
  931. Boolean TTranscriptWindow::IsLogWindowEvent (const EventRecord& event )
  932. {
  933.     Boolean        result = false;
  934.  
  935.     switch ( event.what )
  936.     {
  937.         case mouseDown:
  938.         {
  939.             {    WindowPtr        WindowPointedTo;        //window where the mouse is
  940.                 Point MouseLoc = event.where;
  941.  
  942.                 short WindoPart = FindWindow(MouseLoc, &WindowPointedTo);
  943.                 TTranscriptWindow* logWindow = FindLogWindow ( WindowPointedTo );
  944.                 
  945.                 if ( logWindow )
  946.                 {
  947.                     if (WindowPointedTo != FrontWindow())
  948.                         SelectWindow(WindowPointedTo);
  949.                     else
  950.                         logWindow->MouseDown(WindoPart, MouseLoc, event.modifiers);
  951.                     result = true;
  952.                 }
  953.             }
  954.             break;
  955.         }
  956.             
  957.         case activateEvt:
  958.         {    TTranscriptWindow* logWindow = FindLogWindow ( WindowPtr(event.message) );
  959.             if ( logWindow )
  960.             {
  961.                 logWindow->ActivateEvent ( event.modifiers );
  962.                 result = true;
  963.             }
  964.             break;
  965.         }
  966.             
  967.         case updateEvt:
  968.         {    TTranscriptWindow* logWindow = FindLogWindow ( WindowPtr( event.message ) );
  969.             if ( logWindow )
  970.             {
  971.                 logWindow->UpdateEvent();
  972.                 result = true;
  973.             }
  974.             break;
  975.         }
  976.     }
  977.     
  978.     return result;
  979.     
  980. } //Event
  981.  
  982. /***********************************|****************************************/
  983.  
  984.  
  985. void TTranscriptWindow::AddEncodedText (Ptr dataPtr, long size)
  986. {
  987.     for ( short index = 0; index < size; ++index )
  988.     {
  989.         char c = dataPtr[index];
  990.         switch ( c )
  991.         {
  992.             case  0: case 128: c = 'ø'; break;
  993.             case  8: case 136: c = 'Δ'; break;
  994.             
  995.             case 10: case 138: c = '◊'; break;
  996.             case 13: case 141: c = '¬'; break;
  997.             case 222: c = '∞'; break;
  998.         }
  999.         Append ( &c, 1 );
  1000.     }
  1001. }
  1002.  
  1003. /***********************************|****************************************/
  1004.  
  1005. inline long IntegerMax (long a, long b )
  1006. {
  1007.     return ( a > b ) ? a : b;
  1008. }
  1009.  
  1010. /***********************************|****************************************/
  1011.  
  1012. static Str255& NumToHexStringF(long theNumber)
  1013. {    static Str255        returnStr;
  1014.  
  1015.     returnStr[0] = sprintf ((char*) &returnStr[1], "%8x", theNumber );
  1016.     
  1017.     return returnStr;
  1018. }
  1019.  
  1020. /***********************************|****************************************/
  1021.  
  1022. void TTranscriptWindow::AddHexData (Ptr dataPtr, short dataSize )
  1023. {
  1024.     long        index ;
  1025.     Str255        result ;
  1026.     short        len ;
  1027.     char        byte ;
  1028.  
  1029.     if ( !dataPtr )
  1030.     {        
  1031.         DebugStr ("\pNo data dump, NULL data ptr");
  1032.         return;
  1033.     }
  1034.  
  1035.     if ( dataSize <= 0 )
  1036.     {
  1037.         DebugStr ("\pNo data dump, datesize <= 0");
  1038.         return;
  1039.     }
  1040.     
  1041.     long offset = 0;
  1042.  
  1043.     while (offset < dataSize)
  1044.     {
  1045.         #if 0
  1046.         Append (
  1047.         write ( NumToHexStringF (offset), ':');
  1048.  
  1049.         // Put it into a Str255 because it's faster to add one string to the window than it is to add 16 
  1050.         result = '';
  1051.         for index = 0 to 15
  1052.         do
  1053.             if offset + index < dataSize
  1054.             then
  1055.                 begin
  1056.                 len = length(result);
  1057.                 byte = BytePtr(((long)dataPtr)+offset+index)^;
  1058.                 result[len+1] = fHexStr[ ((byte) >> 4)];
  1059.                 result[len+2] = fHexStr[ ((byte) & 0xF)];
  1060.                 result[len+3] = ' ';
  1061.                 //$PUSH*/ /*$R-*/ result[0] = ((char)(len + 3)); /*$POP
  1062.                 end
  1063.             else
  1064.                 begin
  1065.                 result[len+1] = ' ';
  1066.                 result[len+2] = ' ';
  1067.                 result[len+3] = ' ';
  1068.                 //$PUSH*/ /*$R-*/ result[0] = ((char)(len + 3)); /*$POP
  1069.                 end();
  1070.         write (result, '| ');
  1071.  
  1072.         AddEncodedText ( Ptr(((long)dataPtr)+offset), IntegerMax(dataSize - offset, 16));
  1073.  
  1074.         offset = offset + 16;
  1075.         #endif
  1076.     }
  1077. }
  1078.  
  1079. /***********************************|****************************************/
  1080.  
  1081. void TTranscriptWindow::Show (void)
  1082. {
  1083.     if ( ! fDebugWindowPtr )
  1084.         Initialize ( );
  1085.         
  1086.     SetDefaultWindowInformation ( fDebugWindowPtr, -1 );
  1087.  
  1088.     ShowWindow (fDebugWindowPtr);
  1089. }
  1090.  
  1091. /***********************************|****************************************/
  1092.